from zope.interface import implements
from twisted.internet import interfaces, reactor
from twisted.internet.protocol import Factory, ClientFactory, ReconnectingClientFactory
from twisted.protocols.basic import LineReceiver
from time import time
import os, sys

class Info:
    def __init__(self):
        self.name = ''
        self.port = 0
        self.dRate = 0.0
        self.uRate = 0.0

    def getName(self):
        return self.name

    def setName(self, name):
        self.name = name

    def setListenPort(self, port):
        self.port = port

    def getListenPort(self):
        return self.port

    def setDownRate(self, dRate):
        self.dRate = dRate

    def getDownRate(self):
        return self.dRate

    def setUpRate(self, uRate):
        self.uRate = uRate

    def getUpRate(self):
        return self.uRate
        

class ClientInfo:
    def getName(self):
        return self.name

    def setName(self, name):
        self.name = name

    def setListenPort(self, port):
        self.port = port

    def getListenPort(self):
        return self.port

class ServerInfo:
    def __init__(self):
        self.name = ''
        self.port = 0
        
    def getName(self):
        return self.name

    def setName(self, name):
        self.name = name

    def setConnectPort(self, port):
        self.port = port

    def getConnectPort(self):
        return self.port
    
serverInfo = ServerInfo()
info = Info()
clientInfo = ClientInfo()
    
class ContentProducer:
  implements(interfaces.IPushProducer)
  def __init__(self, protocol):
    self.protocol = protocol
    self.paused = False
    self.lineCount = 0
    self.startTime = 0
    self.delay = 0.0
  def pauseProducing(self):
    print "ContentProducer paused"
    self.paused = True
  def resumeProducing(self):
    print "ContentProducer resuming"
    self.paused = False
    if not self.startTime:
      self.startTime = time()
    while not self.paused:
      self.protocol.transport.write("Hello world\r\n")
      self.lineCount += 1
      if self.lineCount % 1000 == 0:
        info.setUpRate(str(self.lineCount / (time()-self.startTime)))
        print "rate = %.2f lines / second" % (self.lineCount / (time()-self.startTime))
  def stopProducing(self):
    pass

class NodeProtocol(LineReceiver):

  def __init__(self):
      self.lineCount = 0
      self.startTime = 0
      
  def connectionMade(self):
    print "%s.connectionMade" % self.factory.name
    self.sendLine(info.getName()+ " " + info.getListenPort())  
    self.sendLine("uconnect:"+info.getName()+ "@@"+str(0.0)+'@@'+str(0.0)+'@@None@@None')
    if self.factory.name == 'A':
      self.producer = ContentProducer(self)
      self.transport.registerProducer(self.producer, True)
      self.producer.resumeProducing()

  def lineReceived(self, line):
    self.lineCount += 1
    if line.startswith("connect:"):
        self.content = line[8:].split()
        serverInfo.setName(self.content[0])
        serverInfo.setConnectPort(int(self.content[1]))
        cFactory = NodeClientFactory("B")
        reactor.connectTCP("localhost", serverInfo.getConnectPort(), cFactory)

    if self.lineCount % 10000 == 0:
          #self.lineCount / (time()-self.startTime) = self.lineCount / (time()-self.startTime)
          info.setDownRate(str(self.lineCount / (time()-self.startTime)))
          self.startTime = time()
          
    if line == 'get':
        self.sendLine("data:"+info.getName() + '@@' + str(info.getDownRate())+ '@@'+str(info.getUpRate())+'@@'+serverInfo.getName()+'@@Nones')
        
  def connectionLost(self, reason):
    print "%s.connectionLost(%s)" % (self.factory.name, reason)

class NodeFactory(Factory):
  protocol = NodeProtocol
  isServer = True
  def __init__(self, name):
    self.name = name

class NodeClientFactory(ClientFactory):
  protocol = NodeProtocol
  isServer = False
  def __init__(self, name):
    self.name = name
    self.retry_count = 0

#class ANode:
#  port = 2000 
#  def __init__(self):
#    """ it's a server """
#    self.factory = NodeFactory("A")
#    reactor.listenTCP(self.port, self.factory)

#class BNode:
#  def __init__(self):
#    """ it's a client """
#    self.factory = NodeClientFactory("B")
#    reactor.connectTCP("localhost", ANode.port, self.factory)

cFactory = NodeClientFactory("B")
sFactory = NodeFactory("A")
if len(sys.argv) == 3:
    info.setName(sys.argv[1])
    info.setListenPort(sys.argv[2])
    reactor.connectTCP("localhost", 2000, cFactory)
    reactor.connectTCP("localhost", 3000, cFactory)
    reactor.listenTCP(int(sys.argv[2]), sFactory)
    reactor.run()
            